﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using System.Reflection;
using Subtle.Domain.Services.Interfaces;
using Subtle.Data.Persistence.Interfaces;
using Subtle.Domain.Models;
using System.Security.Cryptography;

namespace Subtle.Domain.Services
{
	/// <summary>
	/// User Repository
	/// </summary>
	public class UserService : IUserService
	{
		private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

		private IRepository repository;
		private IEmailService emailService;

		/// <summary>
		/// User Service
		/// </summary>
		/// <param name="userUnitOfWork"></param>
		/// <param name="emailService"></param>
		public UserService(IRepository repository, IEmailService emailService)
		{
			this.repository = repository;
			this.emailService = emailService;
		}

		/// <summary>
		/// Create User
		/// </summary>
		/// <param name="user"></para>m
		/// <returns></returns>
		public UserCreateStatus CreateNonValidatedUser(User user)
		{
			//When creating a user, create the new Verification Guid
			user.VerificationGuid = Guid.NewGuid().ToString();

			//Also, the service is required to hash the password
			user.Password = HashPassword(user.Password);

			if (repository.Save<User>(user))
			{
				return UserCreateStatus.Success;
			}
			return UserCreateStatus.Failed;
		}

		/// <summary>
		/// Create User
		/// </summary>
		/// <param name="user"></para>m
		/// <returns></returns>
		public UserCreateStatus CreateValidatedUser(User user)
		{
			//When creating a user, create the new Verification Guid
			user.VerificationGuid = Guid.NewGuid().ToString();
			//Set the user to verified
			user.Verified = true;

			//Also, the service is required to hash the password
			user.Password = HashPassword(user.Password);

			if (repository.Save<User>(user))
			{
				return UserCreateStatus.Success;
			}
			return UserCreateStatus.Failed;
		}

		/// <summary>
		/// Send Validate User Request
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public bool SendValidateUserRequest(User user)
		{
			string subject = @"Welcome to Subtle! Account Activation";
			string body = String.Format("Welcome to Subtle, Please click on the following <a href='http://subtle.co.za/Activate?username={0}&id={1}'>link</a> to activate your account", user.Username, user.VerificationGuid);
			string to = user.Username;

			return emailService.Send(to, null, subject, body);
		}

		/// <summary>
		/// Validate User
		/// </summary>
		/// <param name="user"></param>
		/// <param name="validationGuid"></param>
		/// <returns></returns>
		public bool ValidateUser(User user, string validationGuid)
		{
			if (user.VerificationGuid == validationGuid)
			{
				user.Verified = true;
				return repository.Save<User>(user);
			}
			return false;
		}

		/// <summary>
		/// Get a User
		/// </summary>
		/// <param name="userID"></param>
		/// <returns></returns>
		public User GetUser(int userID)
		{
			return (from user in repository.Query<User>()
					where user.ID == userID
					select user).FirstOrDefault();
		}

		/// <summary>
		/// Get User
		/// </summary>
		/// <param name="username"></param>
		/// <returns></returns>
		public User GetUser(string username)
		{
			return (from user in repository.Query<User>()
					where user.Username == username
					select user).FirstOrDefault();
		}

		/// <summary>
		/// Get User
		/// </summary>
		/// <param name="username"></param>
		/// <param name="password"></param>
		/// <returns></returns>
		public User GetUser(string username, string password)
		{
			string hashedPassword = HashPassword(password);
			var userQuery = (from user in repository.Query<User>()
							 where user.Username == username
							 select user).FirstOrDefault();

			return String.Compare(userQuery.Password, hashedPassword) == 0 ? userQuery : null;
		}

		/// <summary>
		/// Change Password
		/// </summary>
		/// <param name="user"></param>
		/// <param name="newPassword"></param>
		/// <returns>Returns true if the Password change was successul</returns>
		public bool ChangePassword(User user, string newPassword)
		{
			user.Password = newPassword;
			return repository.Save<User>(user);
		}

		/// <summary>
		/// Change the User's Email Address
		/// </summary>
		/// <param name="user"></param>
		/// <param name="newEmailAddress"></param>
		/// <returns>Returns true if the Password change was successul</returns>
		public bool ChangeEmailAddress(User user, string newEmailAddress)
		{
			if (GetUser(newEmailAddress) == null)
			{
				user.Username = newEmailAddress;
				return repository.Save<User>(user);
			}
			return false;
		}

		/// <summary>
		/// Send Password Reminder
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public bool SendPasswordReminder(User user)
		{
			string subject = @"SmartBudget Password Reminder";
			string body = String.Format("Your account details are<br/><br/>Username : {0}<br/>Password : {1}", user.Username, user.Password);
			string to = user.Username;

			return emailService.Send(to, null, subject, body);
		}

		/// <summary>
		/// Hash Password
		/// </summary>
		/// <param name="originalPassword"></param>
		/// <returns></returns>
		public string HashPassword(string originalPassword)
		{
			byte[] bytes = Encoding.Unicode.GetBytes(originalPassword);
			byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
			return Convert.ToBase64String(inArray);
		}
	}

	/// <summary>
	/// User Create Status
	/// </summary>
	public enum UserCreateStatus
	{
		Success,
		Failed,
		UserNotActivated
	}
}
